package org.jeecg.modules.rental.util;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import org.jeecg.boot.starter.lock.client.RedissonLockClient;
import org.jeecg.modules.rental.entity.RentalStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Date;
import java.util.Random;

@Component
public class OrderSnUtil {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedissonLockClient redissonLockClient;

    private static final String SERIAL_NUMBER_PREFIX = "rental:serialNumber:";
    private static final int EXPIRE_AFTER_SECONDS = 24 * 60 * 60; // 1 day in seconds

    public static final DateTimeFormatter START_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmm");
    public static final DateTimeFormatter END_TIME_FORMATTER = DateTimeFormatter.ofPattern("MMddHHmm");
    /**
     * 获取下一个流水号
     * @param orgCode 运营商
     * @return
     */
    public String getNextSerialNumber(String orgCode) {
        String today = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String key = SERIAL_NUMBER_PREFIX + orgCode +":"+ today;

        // 使用Lua脚本来确保原子性
        String luaScript = "if redis.call('exists', KEYS[1]) == 1 then " +
                "    return redis.call('incr', KEYS[1]) " +
                "else " +
                "    redis.call('set', KEYS[1], '1', 'EX', ARGV[1], 'NX') " +
                "    return '1' " +
                "end";

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(luaScript);
        redisScript.setResultType(Long.class);

        Long serialNumber = (Long) redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(EXPIRE_AFTER_SECONDS));
        // 将Long类型转换为String，并添加前缀
        if(null == serialNumber){
            return "0001"; // 假设流水号最大为4位
        }
        return String.format("%04d", serialNumber); // 假设流水号最大为4位
    }

    /**
     * 获取租车订单编号
     * @return
     */
    public String getRentalOrderSn(RentalStore rentalStore, LocalDateTime startTime, LocalDateTime endTime) {
        String lockKey = "rentalOrderLock:" + rentalStore.getSysOrgCode();
        boolean lockAcquired = redissonLockClient.tryLock(lockKey, 2); // 尝试获取锁，锁定时间为10秒

        if (!lockAcquired) {
            throw new RuntimeException("无法获取分布式锁，请稍后重试");
        }
        try {
        StringBuffer orderSn = new StringBuffer();
        String sn = getNextSerialNumber(rentalStore.getSysOrgCode()); //运营商流水号
        orderSn.append(sn);
        orderSn.append("-");

        String zipCode = rentalStore.getZipCode(); //门店所在城市邮政编号
        orderSn.append(zipCode);
        orderSn.append("-");

        String storeCategory = rentalStore.getStoreCategory(); //门店类别
        orderSn.append(storeCategory);
        orderSn.append("-");

        String storeCode = rentalStore.getMeshPointsCode(); //门店编号
        orderSn.append(storeCode);
        orderSn.append("-");

        orderSn.append(startTime.format(START_TIME_FORMATTER));
        orderSn.append("T");
        orderSn.append(endTime.format(END_TIME_FORMATTER));
        return orderSn.toString();
        } finally {
            redissonLockClient.unlock(lockKey); // 释放锁
        }
    }

    /**
     * 获取租车交易编号
     * @return
     */
    public String getRentalTradeCode() {
        SimpleDateFormat simpleDateFormat;
        simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        String str = simpleDateFormat.format(date);
        Random random = new Random();
        int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数
        return str + rannum;// 当前时间
    }


    public String getCouponCode(String type) {
        //String today = new SimpleDateFormat("yyyyMMdd").format(new Date());

        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        long snowflakeId = snowflake.nextId();
        String timestamp = String.valueOf(System.currentTimeMillis()); // 获取当前时间戳
        String serialNumber = String.format("%04d", snowflakeId % 10000); // 生成 4 位流水号

        return type +   timestamp + serialNumber;
    }

    /**
     * 获取商户编号
     * @param lastCode
     * @return
     */
    public String getMerchantCode(String lastCode) {
        if(null == lastCode || "".equals(lastCode) ){
            return "00";
        }
        char firstChar = lastCode.charAt(0);
        char secondChar = lastCode.charAt(1);

        // 检查是否到达ZZ，如果是则抛出异常或采取其他策略
        if (firstChar == 'Z' && secondChar == 'Z') {
            throw new IllegalStateException("Reached the end of merchant code sequence: ZZ");
        }

        // 如果第二位是字母且不是Z，则只递增第二位
        if (Character.isLetter(secondChar) && secondChar != 'Z') {
            return String.valueOf(firstChar) + Character.toString((char) (secondChar + 1));
        }

        // 如果第二位是Z或9
        if (secondChar == 'Z' || (Character.isDigit(firstChar) && secondChar == '9')) {
            // 如果第一位是数字，则将其设置为'A'，第二位重置为'0'
            if (Character.isDigit(firstChar)) {
                firstChar = 'A';
                secondChar = '0';
            } else { // 如果第一位是字母，则递增它，第二位重置为'A'
                firstChar = (char) (firstChar + 1);
                secondChar = 'A';
            }
        } else {
            // 如果第二位是数字且不是9，则只递增第二位
            secondChar = (char) (secondChar + 1);
        }

        return String.valueOf(firstChar) + secondChar;
    }
}
